package com.ryx.shiro.realm;

import com.ryx.constants.Constant;
import com.ryx.service.PermissionService;
import com.ryx.service.RoleService;
import com.ryx.shiro.CustomUsernamePasswordToken;
import com.ryx.utils.JWTTokenUtil;
import com.ryx.utils.RedisUtil;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsPackage: com.ryx.shiro.realm
 * @Author: 容永轩
 * @CreateTime: 2020-11-08
 * @Description: 自定义Realm
 */
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private RedisUtil redisService;


    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof CustomUsernamePasswordToken;
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String accessToken= (String) principals.getPrimaryPrincipal();
        Claims claimsFromToken = JWTTokenUtil.getClaimsFromToken(accessToken);
        //返回该用户的角色信息给授权期
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();

//        if(claimsFromToken.get(Constant.PERMISSIONS_INFOS_KEY)!=null){
//            info.addStringPermissions((Collection<String>) claimsFromToken.get(Constant.PERMISSIONS_INFOS_KEY));
//        }
//        //返回该用户的权限信息给授权器
//        if(claimsFromToken.get(Constant.ROLES_INFOS_KEY)!=null){
//            info.addRoles((Collection<String>) claimsFromToken.get(Constant.ROLES_INFOS_KEY));
//        }

        //拿到当前用户id
        String userId=JWTTokenUtil.getUserId(accessToken);

        //判断是否被标记 是否需要主动刷新token
        //当token需要去主动刷新而没刷新前按钮权限控制 需要从DB获取数据交给授权认证器  这里这么做是为了admin在修改角色的信息时 需要展示的东西减少或者添加时，需要及时修改data
        if(redisService.hasKey(Constant.JWT_REFRESH_KEY+userId)&&redisService.getExpire(Constant.JWT_REFRESH_KEY+userId, TimeUnit.MILLISECONDS)>JWTTokenUtil.getRemainingTime(accessToken)){
            //拿到每个角色的名字Name
            List<String> roles=roleService.getNamesByUserId(userId);
            if(roles!=null&&!roles.isEmpty()){
                //不为空就加到授权器中
                info.addRoles(roles);
            }

            //拿到权限信息
            List<String> permissionByUserId = permissionService.getPermissionByUserId(userId);
            if(permissionByUserId!=null&&!permissionByUserId.isEmpty()){
                info.addStringPermissions(permissionByUserId);
            }

        }else {
            if(claimsFromToken.get(Constant.PERMISSIONS_INFOS_KEY)!=null){
                info.addStringPermissions((Collection<String>) claimsFromToken.get(Constant.PERMISSIONS_INFOS_KEY));
            }
            if(claimsFromToken.get(Constant.ROLES_INFOS_KEY)!=null){
                info.addRoles((Collection<String>) claimsFromToken.get(Constant.ROLES_INFOS_KEY));
            }
        }

        return info;
    }
    //认证
    //我们这里返回给认证器的用户凭证credentials就是我们前端请求接口携带的业务token
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        CustomUsernamePasswordToken customUsernamePasswordToken= (CustomUsernamePasswordToken) token;
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(customUsernamePasswordToken.getPrincipal(),customUsernamePasswordToken.getCredentials(),this.getName());
        return info;
    }
}
